/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. */ package org.thingml.compilers.java; import org.sintef.thingml.*; import org.sintef.thingml.constraints.ThingMLHelpers; import org.sintef.thingml.constraints.Types; import org.sintef.thingml.helpers.*; import org.thingml.compilers.Context; import org.thingml.compilers.thing.common.CommonThingActionCompiler; /** * Created by bmori on 01.12.2014. */ public class JavaThingActionCompiler extends CommonThingActionCompiler { @Override public void generate(Increment action, StringBuilder builder, Context ctx) { if (action.getVar().getProperty() instanceof Property) { builder.append("set" + ctx.firstToUpper(ctx.getVariableName(action.getVar().getProperty())) + "("); builder.append("(" + JavaHelper.getJavaType(action.getVar().getProperty().getType(), action.getVar().getProperty().getCardinality() != null, ctx) + ")"); builder.append("(get" + ctx.firstToUpper(ctx.getVariableName(action.getVar().getProperty())) + "()"); builder.append(" + 1));\n"); } else { super.generate(action, builder, ctx); } } @Override public void generate(Decrement action, StringBuilder builder, Context ctx) { if (action.getVar().getProperty() instanceof Property) { builder.append("set" + ctx.firstToUpper(ctx.getVariableName(action.getVar().getProperty())) + "("); builder.append("(" + JavaHelper.getJavaType(action.getVar().getProperty().getType(), action.getVar().getProperty().getCardinality() != null, ctx) + ")"); builder.append("(get" + ctx.firstToUpper(ctx.getVariableName(action.getVar().getProperty())) + "()"); builder.append(" - 1));\n"); } else { super.generate(action, builder, ctx); } } @Override public void generate(EqualsExpression expression, StringBuilder builder, Context ctx) { //FIXME: avoid duplication final Type leftType = ctx.getCompiler().checker.typeChecker.computeTypeOf(expression.getLhs()); final Type rightType = ctx.getCompiler().checker.typeChecker.computeTypeOf(expression.getRhs()); if (TyperHelper.isA(leftType, Types.OBJECT_TYPE)) { if (expression.getRhs() instanceof ExternExpression) { final ExternExpression ext = (ExternExpression) expression.getRhs(); if (ext.getExpression().trim().equals("null")) {//we check for null pointer, should use == super.generate(expression, builder, ctx); return; } } generate(expression.getLhs(), builder, ctx); builder.append(".equals("); generate(expression.getRhs(), builder, ctx); builder.append(")"); } else if (TyperHelper.isA(rightType, Types.OBJECT_TYPE)) { if (expression.getLhs() instanceof ExternExpression) { final ExternExpression ext = (ExternExpression) expression.getLhs(); if (ext.getExpression().trim().equals("null")) {//we check for null pointer, should use == super.generate(expression, builder, ctx); return; } } generate(expression.getRhs(), builder, ctx); builder.append(".equals("); generate(expression.getLhs(), builder, ctx); builder.append(")"); } else { super.generate(expression, builder, ctx); } } @Override public void generate(NotEqualsExpression expression, StringBuilder builder, Context ctx) { //FIXME: avoid duplication final Type leftType = ctx.getCompiler().checker.typeChecker.computeTypeOf(expression.getLhs()); final Type rightType = ctx.getCompiler().checker.typeChecker.computeTypeOf(expression.getRhs()); if (TyperHelper.isA(leftType, Types.OBJECT_TYPE)) { if (expression.getRhs() instanceof ExternExpression) { final ExternExpression ext = (ExternExpression) expression.getRhs(); if (ext.getExpression().trim().equals("null")) {//we check for null pointer, should use == super.generate(expression, builder, ctx); return; } } builder.append("!("); generate(expression.getLhs(), builder, ctx); builder.append(".equals("); generate(expression.getRhs(), builder, ctx); builder.append("))"); } else if (TyperHelper.isA(rightType, Types.OBJECT_TYPE)) { if (expression.getRhs() instanceof ExternExpression) { final ExternExpression ext = (ExternExpression) expression.getLhs(); if (ext.getExpression().trim().equals("null")) {//we check for null pointer, should use == super.generate(expression, builder, ctx); return; } } builder.append("!("); generate(expression.getRhs(), builder, ctx); builder.append(".equals("); generate(expression.getLhs(), builder, ctx); builder.append("))"); } else { super.generate(expression, builder, ctx); } } @Override public void traceVariablePre(VariableAssignment action, StringBuilder builder, Context ctx) { /*if ((action.getProperty().eContainer() instanceof Thing) && action.getProperty().getCardinality() == null) {//FIXME: support debugging of arrays (needs to copy array) builder.append("debug_" + ctx.getVariableName(action.getProperty()) + " = " + ctx.getVariableName(action.getProperty()) + ";\n"); }*/ } @Override public void traceVariablePost(VariableAssignment action, StringBuilder builder, Context ctx) { /*if ((action.getProperty().eContainer() instanceof Thing) && action.getProperty().getCardinality() == null) {//FIXME: see above //builder.append("if(isDebug()) System.out.println(org.fusesource.jansi.Ansi.ansi().eraseScreen().render(\"@|magenta \" + getName() + \": property " + action.getProperty().getName() + " changed from \" + debug_" + ctx.getVariableName(action.getProperty()) + " + \" to \" + " + ctx.getVariableName(action.getProperty()) + " + \"|@\"));\n"); builder.append("if(isDebug()) " + "System.out.println(getName() + \": property " + action.getProperty().getName() + " changed from \" + debug_" + ctx.getVariableName(action.getProperty()) + " + \" to \" + " + ctx.getVariableName(action.getProperty()) + ");\n"); }*/ } @Override public void generate(SendAction action, StringBuilder builder, Context ctx) { builder.append("send" + ctx.firstToUpper(action.getMessage().getName()) + "_via_" + action.getPort().getName() + "("); int i = 0; for (Expression p : action.getParameters()) { if (i > 0) builder.append(", "); int j = 0; for (Parameter fp : action.getMessage().getParameters()) { if (i == j) {//parameter p corresponds to formal parameter fp cast(fp.getType(), fp.isIsArray(), p, builder, ctx); break; } j++; } i++; } builder.append(");\n"); } @Override public void generate(StartSession action, StringBuilder builder, Context ctx) { builder.append("final Component " + action.getSession().getName() + " = new " + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + "(\"" + action.getSession().getName() + "\""); for (Property p : ThingHelper.allPropertiesInDepth(ThingMLHelpers.findContainingThing(action.getSession()))) { builder.append(", "); if (p.isIsArray() || p.getCardinality() != null) { builder.append("Arrays.copyOf(" + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this." + ctx.getVariableName(p) + ", " + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this." + ctx.getVariableName(p) + ".length)"); } else { builder.append(ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this." + ctx.getVariableName(p)); } } builder.append(").buildBehavior(\"" + action.getSession().getName() + "\", " + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this);\n"); builder.append("final Component root = (" + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this.root == null)? " + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this : " + ctx.firstToUpper(ThingMLHelpers.findContainingThing(action.getSession()).getName()) + ".this.root;\n"); builder.append("root.addSession(" + action.getSession().getName() + ");\n"); } @Override public void generate(StartStream action, StringBuilder builder, Context ctx) { //if(action.getStream().getInput() instanceof SimpleSource) { builder.append("start" + ThingMLElementHelper.qname(action.getStream().getInput(), "_") + "();\n"); /*} else if (action.getStream().getInput() instanceof SourceComposition) { builder.append("start" + action.getStream().qname("_") + "();\n"); }*/ } @Override public void generate(StopStream action, StringBuilder builder, Context ctx) { //if(action.getStream().getInput() instanceof SimpleSource) { builder.append("stop" + ThingMLElementHelper.qname(action.getStream().getInput(), "_") + "();\n"); /*} else if (action.getStream().getInput() instanceof SourceComposition) { builder.append("stop" + action.getStream().qname("_") + "();\n"); }*/ } @Override public void generate(FunctionCallStatement action, StringBuilder builder, Context ctx) { if (AnnotatedElementHelper.isDefined(action.getFunction(), "fork_thread", "true") && action.getFunction().getType() != null) { System.err.println("function " + action.getFunction().getName() + "cannot be called with @fork_thread, as its return type (" + action.getFunction().getType().getName() + ") is not void"); throw new UnsupportedOperationException("function " + action.getFunction().getName() + "cannot be called with @fork_thread, as its return type (" + action.getFunction().getType().getName() + ") is not void"); } if (AnnotatedElementHelper.isDefined(action.getFunction(), "fork_thread", "true")) { builder.append("new Thread(new Runnable(){public void run() {\n"); } builder.append(action.getFunction().getName() + "("); int i = 0; for (Expression p : action.getParameters()) { if (i > 0) builder.append(", "); int j = 0; for (Parameter fp : action.getFunction().getParameters()) { if (i == j) {//parameter p corresponds to formal parameter fp cast(fp.getType(), fp.isIsArray(), p, builder, ctx); break; } j++; } i++; } builder.append(");\n"); if (AnnotatedElementHelper.isDefined(action.getFunction(), "fork_thread", "true")) { builder.append("}}).start();\n"); } } @Override public void generate(LocalVariable action, StringBuilder builder, Context ctx) { if (!action.isChangeable()) { builder.append("final "); } //Define the type of the variable builder.append(JavaHelper.getJavaType(action.getType(), action.isIsArray(), ctx)); builder.append(" "); builder.append(ctx.getVariableName(action)); //Define the initial value for that variable if (action.getInit() != null) { builder.append(" = "); cast(action.getType(), action.isIsArray(), action.getInit(), builder, ctx); builder.append(";\n"); } else { if (!action.isChangeable()) { System.err.println("WARNING: non changeable variable (" + action.getName() + ") should have been initialized "); builder.append("/*final variable should have been initialized. Please fix your ThingML model*/"); } if (action.getCardinality() != null) { builder.append(" = new " + JavaHelper.getJavaType(action.getType(), false, ctx) + "["); generate(action.getCardinality(), builder, ctx); builder.append("];"); } else { if (AnnotatedElementHelper.isDefined(action.getType(), "java_primitive", "true")) { builder.append(" = " + JavaHelper.getDefaultValue(action.getType()) + ";"); } else { builder.append(" = null;"); } } } builder.append("\n"); } @Override public void generate(ErrorAction action, StringBuilder builder, Context ctx) { builder.append("System.err.print("); generate(action.getMsg(), builder, ctx); builder.append(");\n"); } @Override public void generate(PrintAction action, StringBuilder builder, Context ctx) { builder.append("System.out.print("); generate(action.getMsg(), builder, ctx); builder.append(");\n"); } @Override protected void generateReference(Message message, String messageName, Reference expression, StringBuilder builder, Context ctx) { String paramResult = ""; if (expression.getParameter() instanceof ParamReference) { if (expression.getParameter() instanceof SimpleParamRef) paramResult = "."; ParamReference paramReference = (ParamReference) expression.getParameter(); //this method is called only when the reference parameter is a ParamReference builder.append(ctx.protectKeyword(messageName) + paramResult + ctx.protectKeyword(paramReference.getParameterRef().getName())); } else {//else : ArrayParamRef builder.append(ctx.protectKeyword(messageName) + ".size()"); } } @Override public void generate(PropertyReference expression, StringBuilder builder, Context ctx) { if (!ctx.getAtInitTimeLock()) { if (expression.getProperty() instanceof Property && ((Property) expression.getProperty()).getCardinality() == null) builder.append("get" + ctx.firstToUpper(ctx.getVariableName(expression.getProperty())) + "()"); else builder.append(ctx.getVariableName(expression.getProperty())); } else { Property p = (Property) expression.getProperty(); if (p.isChangeable()) { System.out.println("Error: non Read-only property (" + p.getName() + ") used in array cardinality definition."); } Expression e = ConfigurationHelper.initExpressions(ctx.getCurrentConfiguration(), ctx.currentInstance, p).get(0); generate(e, builder, ctx); } } @Override public void generate(EnumLiteralRef expression, StringBuilder builder, Context ctx) { builder.append(ctx.firstToUpper(expression.getEnum().getName()) + "_ENUM." + ((ThingMLElement) expression.getLiteral().eContainer()).getName().toUpperCase() + "_" + expression.getLiteral().getName().toUpperCase()); } @Override public void generate(FunctionCallExpression expression, StringBuilder builder, Context ctx) { builder.append(expression.getFunction().getName() + "("); int i = 0; for (Expression p : expression.getParameters()) { if (i > 0) builder.append(", "); int j = 0; for (Parameter fp : expression.getFunction().getParameters()) { if (i == j) {//parameter p corresponds to formal parameter fp cast(fp.getType(), fp.isIsArray(), p, builder, ctx); break; } j++; } i++; } builder.append(")"); } @Override public void cast(Type type, boolean isArray, Expression exp, StringBuilder builder, Context ctx) { if (!(type instanceof Enumeration)) { if (AnnotatedElementHelper.hasAnnotation(type, "java_type")) { if (!isArray) builder.append("(" + AnnotatedElementHelper.annotation(type, "java_type").toArray()[0] + ") "); else builder.append("(" + AnnotatedElementHelper.annotation(type, "java_type").toArray()[0] + "[]) "); } else { if (!isArray) builder.append("(Object) "); else builder.append("(Object[]) "); } } builder.append("("); generate(exp, builder, ctx); builder.append(")"); } }